home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / bump.exe / BUMP.DOC < prev    next >
Text File  |  1991-02-10  |  20KB  |  407 lines

  1.  
  2.                                  BUMP 1.1
  3.  
  4.                 A Beginner's Understandable Matrix Package 
  5.                                in Borland C++
  6.  
  7. From the dawn of programming, people have wanted to be able to write
  8. something like
  9.  
  10.      Matrix A(4,4), B(4,4), C(4,4), D(4,4);
  11.      ...
  12.      A = (B + C)* D;
  13.  
  14. and get in the A matrix the result expected from matrix algebra.  The best
  15. that languages like Fortran, Basic, Pascal, or C could offer, however, was
  16. either a lot of function calls or loops on subscripts.  Special matrix
  17. interpreters were developed which, however, limited what you could do.  If
  18. what you wanted to do, say graph the diagonal of a matrix, couldn't be done
  19. by your package, you were stuck.  Also, you frequently had to master large
  20. manuals for one special-purpose program.   With C++, however, it is
  21. possible for the user to define a data type "Matrix" and then write
  22. functions to "overload" the =, +, and * operators so that when the compiler
  23. recognizes that, say, a + is between two matrices, it will call the user-
  24. written function to add the two matrices.  At the same time, you have all
  25. the flexibility of C and C++ and very little to learn in the way of
  26. special-purpose instructions.   It is just a matter of writing the
  27. necessary code to define the Matrix and Vector data types and to overload
  28. the operators.  
  29.  
  30. Since matrices are so widely used, I had expected that it would be easy to
  31. find examples in books of exactly how to define the data types and write
  32. the overloaded operator functions.  I found hints and fragments, but no
  33. fully worked out satisfactory solution.  In particular, the examples in the
  34. books tended to be bad about loosing track of memory that had been
  35. allocated for temporary matrices (like (B + C) in the above example), so
  36. that repeated use of equations like the one above would eventually stop the
  37. program.  Design of the destructors was of the essence for this problem,
  38. and it gets scant attention in most introductions to C++.  On the bulletin
  39. boards, I found two extensive examples at the opposite extreme, Newmat and
  40. Yamp.  They were too complicated to serve as examples.  I learned some
  41. things from them but could not begin to really follow how they worked.  So
  42. I set out on my own to see if I could apply what I thought I knew.  It was
  43. a time-consuming process full of mistakes and enigmatic compiler messages. 
  44. But the result, BUMP, seems well worth the trouble.
  45.  
  46. In BUMP you will find applications of most of the C++ techniques.  It has
  47. classes with functions, derived classes with inheritance, non-trivial
  48. constructors and destructors, overloaded operators, and even a virtual
  49. function.  In the hope that it may be useful to others both as an example
  50. and as a useable product, I have made it publicly available.  I hope that
  51. BUMP may help you over the hump to effective use of C++.
  52.  
  53. BUMP is intentionally a minimal package so that the user can understand it
  54. and extend it in directions of interest to him.  Before trying to read the
  55. code, however, it is probably a good idea to use BUMP as it is a bit so
  56. that you know what its functions do before you trying to read them.
  57. Accordingly, I'll first explain how to use it, and then add a few notes on
  58. reading the code.
  59.  
  60. Use of BUMP
  61.  
  62. To use BUMP as it is, you write a program in C++.  Don't worry if you know
  63. only C and not C++; the code you write can be pure C except for your use of
  64. BUMP's matrix and vector objects.  You must compile your program with the
  65. Borland C++ compiler, so the extension of its filename should be ".cpp". 
  66. Your program should have among the header lines the line 
  67.      #include "bump.h";
  68.  
  69. and the linker command should link in bump.obj.  Specific directions for
  70. compiling and linking the example are given below. 
  71.  
  72. Those simple measures are all that is necessary to be able to write a
  73. program like the following, which illustrates some of the capabilities of
  74. BUMP:
  75.  
  76.      Vector a(4),at(1,4),c(4),ct(1,4);
  77.      Matrix A(4,4),B(4,4),C(4,4),D(4,1),E(1,1);
  78.  
  79.      // Read in the matrix from an ASCII file and display it
  80.      A.ReadA("amatrix");
  81.      A.Display("Here is the A matrix:");
  82.  
  83.      // Pre-multiply it by a scalar and divide it by a scalar
  84.      B = 2.*A;
  85.      B.Display("This is 2.*A.");
  86.      B = A/2.;
  87.      B.Display("and this is A/2.");
  88.      tap();
  89.  
  90.      // Invert it. A ! in front of the matrix is the sign for inverse.
  91.      B = !A; 
  92.      B.Display("and here is B = !A ( A inverse):");
  93.  
  94.      // Multiply two matrices:
  95.      C = A*B;
  96.      // This next Display will have column width of 15 and 6 decimal places
  97.      C.Display("This is A*!A (should be I):",15,6);
  98.  
  99.      // Parentheses work as expected:
  100.      B = (A + A)*!A;
  101.      B.Display("B = (A+A)*!A. Should be 2I");
  102.  
  103.      C = A*A;
  104.      C.Display("A*A:");
  105.      C = (A+A)*(A+A);
  106.      C.Display("(A+A)*(A+A). Should be 4 times the matrix above.");
  107.  
  108.      // Take the transpose. A ~ in front of a matrix indicates transpose.
  109.      B = ~A;
  110.      A.Display("Here is A again.");
  111.      B.Display("and this is ~A, A transpose.");
  112.  
  113.      // Now some tests with vectors
  114.      a.ReadA("avector");
  115.      at = ~a;
  116.      a.Display("This is the a vector:");
  117.      at.Display("and this is its transpose. The difference doesn't show.");
  118.      D << a;
  119.      D.Display("And this is D << a :");
  120.  
  121.      c = A*a;
  122.      c.Display("This is  A*a");
  123.      ct = ~a*~A;
  124.      ct.Display("This is ~a*~A. Should look the same as the above.");
  125.  
  126.      // Tests of the / operator.  A/A is A'A computed without taking A'.
  127.      B = ~A*A;
  128.      B.Display("This is ~A*A");
  129.      B = A/A;
  130.      B.Display("This is A/A. Should be the same as the above.");
  131.  
  132.      c = A/a;
  133.      ct = a/A;
  134.      c.Display("This is A/a:");
  135.      ct.Display("This is a/A. Should look like the above.");
  136.  
  137.      E = a/a;
  138.      B = at/at;
  139.      E.Display("This is a/a:");
  140.      B.Display("This is at/at:");
  141.      printf("\nEnd of test.\n");
  142.      }
  143.  
  144. From this example, we see that BUMP has an extended data type Matrix.  A
  145. matrix has a function (ReadA) to read data into it from an ASCII file and
  146. another function (Display) to display the matrix on the screen.  The =,
  147. +, -, and * operators have their expected definitions.  Parentheses work in
  148. the expected way. A ~ in front of a Matrix calculates its transpose, while
  149. a ! in front of a Matrix calculates its inverse (by a primitive algorithm).
  150. Neither affects the Matrix itself. (Perhaps you don't like ~ for
  151. transposition and ! for inversion.  The ' operator, however, is not
  152. available in C++ for overloading; the ^, which I would have preferred for
  153. inversion, is a binary operator in C++ and cannot be used for a unary
  154. process like inversion or transposition.  There is, in fact, not much
  155. alternative to ~ and ! for these two unary operations.)
  156.  
  157. BUMP also has a Vector data type. All the same functions and operators
  158. (except, of course, !) apply to Vectors, and to Vectors and Matrices
  159. together, where dimensions are appropriate. 
  160.  
  161. Pre-multiplication of a Vector or Matrix by a float (a scalar) has been
  162. defined, as has division of a Matrix or Vector by a float.  I did not
  163. bother to define post-multiplication of a vector or matrix by a float.
  164.  
  165. Matrix division does not occur, so the / operator is available to mean
  166. something else.  In statistical computations, expressions like X'X or Z'X -
  167. - ~X*X or ~Z*X in BUMP notation -- occur frequently with X' or Z' being
  168. large matrices so that it undesirable to clog up scarce memory by actually
  169. taking the transpose.  These products can, of course, be computed directly
  170. from X and Z.  That is what Z/X does in BUMP; it computes ~Z*X without ever
  171. creating ~Z.
  172.  
  173.  
  174.    To convert a Vector, v, to a Matrix, M, one uses
  175.  
  176.      M << v;
  177.  
  178. Finally, element i of Vector v is denoted by v[i] on either side of the =
  179. sign, while element (i,j) of Matrix M is denoted by M[i][j] on either side
  180. of an =.  The Vector elements are range-checked on both sides of an = sign.
  181. Thus, if v has 20 elements and you ask for v[23], you will get an error
  182. message. The range checking on the Matrix element is only on the row index.